home *** CD-ROM | disk | FTP | other *** search
- *****************************************************************************
- * Program: Cap V1.0 - ©1990 by Jeff Lavin
- * Descrip: Read the capacity of a C-Ltd SCSI Drive.
- * Usage: 1> Cap <unit>
- * Author: Jeff Lavin
- * History: 05/21/90 V1.00 Created
- *
- ******************************* tear here ***********************************
-
- SYS macro ;General purpose macro
- jsr _LVO\1(a6) ;Call the function
- endm
-
- STRUCTURE macro
- \1 set 0
- SOFFSET set \2
- endm
-
- APTR macro
- \1 equ SOFFSET
- SOFFSET set SOFFSET+4
- endm
-
- BPTR macro
- \1 equ SOFFSET
- SOFFSET set SOFFSET+4
- endm
-
- LONG macro
- \1 equ SOFFSET
- SOFFSET set SOFFSET+4
- endm
-
- WORD macro
- \1 equ SOFFSET
- SOFFSET set SOFFSET+2
- endm
-
- BYTE macro
- \1 equ SOFFSET
- SOFFSET set SOFFSET+1
- endm
-
- STRUCT macro
- \1 equ SOFFSET
- SOFFSET set SOFFSET+\2
- endm
-
- LABEL macro
- \1 equ SOFFSET
- endm
-
- SysBase equ 4 ;Exec library base pointer
-
- cd_BoardAddr equ $20 ;ConfigDev Structure
-
- * AutoConfig Board Equates
-
- MANF_CLTD equ 1004 ;Manufacturer number
- PROD_12 equ 12 ;Current product rev number
- PROD_14 equ 14 ;Earlier product rev number
- CLTD_HOST equ 7 ;SCSI Unit number of Host Controller
-
- * Class 00 SCSI Command Structure - (General form, specific commands vary)
-
- sc_cmd equ 0 ;Command OpCode
- sc_adrH equ 1 ;Logical Block Address (MSB)
- sc_adrM equ 2 ;Logical Block Address
- sc_adrL equ 3 ;Logical Block Address (LSB)
- sc_count equ 4 ;Block Count
- sc_reserv equ 5 ;Reserved
-
- * NCR5380 SCSI Host Controller registers - Offset = ([reg] * 2) + 1
- * ------------------------------------------------------------------
- ncr_data equ $01 ;(0) Current SCSI Data (R)
- ; Output Data (W)
- ncr_icmd equ $03 ;(1) Initiator Command (R/W)
- ncr_mode equ $05 ;(2) Mode (R/W)
- ncr_tcmd equ $07 ;(3) Target Command (R/W)
- ncr_bstat equ $09 ;(4) Current SCSI Bus Status (R)
- ; Select Enable (W)
- ncr_stat equ $0B ;(5) Bus and Status (R)
- ; Start DMA Send (W)
- ncr_input equ $0D ;(6) Input Data (R)
- ; Start DMA Target Receive (W)
- ncr_reset equ $0F ;(7) Reset Parity/Interrupts (R)
- ; Start DMA Initiator Receive (W)
- * SCSI Command OpCodes
-
- READ_CAP equ $25
-
- * Equates for Initiator Command Register (1)
-
- ASS_NOT equ %00000000 ;Assert nothing, i.e., free data bus
- ASS_BUS equ %00000001 ;Assert Data Bus
- ASS_ATN equ %00000010 ;Assert Attention
- ASS_SEL equ %00000100 ;Assert Select
- ASS_BSY equ %00001000 ;Assert Busy
- ASS_ACK equ %00010000 ;Assert Acknowledge
- ASS_RST equ %10000000 ;Assert Reset
-
- * Equates for Mode Register (2)
-
- ARBITRATE equ 0 ;Start arbitration
- MONITOR_BSY equ 2 ;Generate busy lost interrupt
-
- * SCSI Information Transfer Phases (for Target Command Register (3))
-
- ASS_IO equ %00000001 ;Assert I/O
- ASS_CD equ %00000010 ;Assert C/D
- ASS_MSG equ %00000100 ;Assert MSG
-
- PH_DOUT equ 0 ;Data Out Phase
- PH_DIN equ ASS_IO ;Data In Phase
- PH_CMD equ ASS_CD ;Command Phase
- PH_STAT equ ASS_IO!ASS_CD ;Status Phase
- PH_MOUT equ ASS_CD!ASS_MSG ;Message Out Phase
- PH_MIN equ ASS_IO!ASS_CD!ASS_MSG ;Message In Phase
-
- * Bit defs for Bus Status Register (4)
-
- BCBS_DBP equ 0 ;Data Bus Parity Status
- BCBS_SEL equ 1 ;Select Phase Status
- BCBS_IO equ 2 ;I/O Direction
- BCBS_CD equ 3 ;Control / Data Status
- BCBS_MSG equ 4 ;Message Phase
- BCBS_REQ equ 5 ;Data Request Status
- BCBS_BSY equ 6 ;SCSI Bus Busy Status
- BCBS_RST equ 7 ;SCSI Bus Reset Status
-
- * Equates for Status Register (5)
-
- PHAS_MATCH equ 3 ;Phase match bit def
- INT_REQ equ 4 ;Interrupt request bit def
- DMA_REQ equ 6 ;DMA request bit def
-
- * Program variables
-
- STRUCTURE WorkArea,0
- APTR InitialSP
- APTR DosBase
- APTR ExpBase
- BPTR stdout
- WORD Error ;Offset into error msg table
- BYTE Device ;SCSI Device number
- BYTE Unit ;Adaptec Unit number
- STRUCT FmtArgs,4*4 ;Format args
- STRUCT SCSICmd,10 ;SCSI Command structure
- STRUCT OutBuf,200 ;Output buffer
- STRUCT DataBuf,256 ;Read data buffer
- LABEL Work_Sizeof
-
- _LVODisable equ -$78
- _LVOEnable equ -$7E
- _LVOCloseLibrary equ -$19E
- _LVORawDoFmt equ -$20A
- _LVOOpenLibrary equ -$228
-
- _LVOWrite equ -$30
- _LVOOutput equ -$3C
-
- _LVOFindConfigDev equ -$48
-
- errfile 'ram:assem.output'
- exeobj
- objfile 'Cap'
-
- Cap lea DT(pc),a5
- movea.l a5,a1 ;Clear BSS section
- move.w #(Work_Sizeof/4)-1,d1
- 1$ clr.l (a1)+
- dbra d1,1$
-
- move.l d0,d2 ;Save cmd line
- movea.l a0,a2
- move.l sp,InitialSP(a5)
-
- movea.l SysBase,a6
- lea DosName(pc),a1
- moveq #0,d0
- SYS OpenLibrary ;Open dos.library
- move.l d0,DosBase(a5)
- beq Exit
-
- movea.l d0,a6
- SYS Output
- move.l d0,stdout(a5)
- beq Cleanup
-
- lea BannerStr(pc),a0
- bsr Puts
-
- move.l d2,d0 ;Get cmd line
- movea.l a2,a0
- lea 0(a0,d0.w),a1
- 2$ cmpi.b #' ',-(a1) ;Eat trailing garbage
- dbhi d0,2$
- blt Instruct ;If no args, error
- clr.b 1(a1) ;Null terminate the string
-
- 3$ move.b (a0)+,d0
- beq Instruct ;No args
- cmpi.b #' ',d0 ;Skip spaces
- beq.s 3$
- cmpi.b #'?',d0 ;Instruct?
- beq Instruct ;"Usage:..."
- subi.b #$30,d0 ;Convert to number
- blt Error1 ;Not a number
- cmpi.b #15,d0 ;Only Units 0 to 15 allowed
- bgt Error1 ;Out of range
- move.b d0,d1
- andi.b #%00000111,d0 ;Extract Device number & save
- move.b d0,Device(a5)
- lsr.b #3,d1 ;Extract Adaptec unit number
- lsl.b #5,d1 ; and move to proper bit pos.
- move.b d1,Unit(a5) ;Save unit
-
- movea.l SysBase,a6
- lea ExpName(pc),a1 ;Open expansion.library
- moveq #0,d0 ;Any version
- SYS OpenLibrary
- move.l d0,ExpBase(a5)
- beq Error2
-
- movea.l d0,a6
- suba.l a0,a0
- move.l #1004,d3
- moveq #14,d2
- move.l d3,d0
- move.l d2,d1
- SYS FindConfigDev
- tst.l d0
- bne.s 4$
-
- suba.l a0,a0
- move.l d3,d0
- moveq #12,d2
- move.l d2,d1
- SYS FindConfigDev
- tst.l d0
- beq Error3
- 4$ movea.l d0,a4 ;Ptr to ConfigDev structure
- movea.l cd_BoardAddr(a4),a4
-
- movea.l a6,a1
- movea.l SysBase,a6
- SYS CloseLibrary
- clr.l ExpBase(a5)
-
- move.b Device(a5),d1
- bsr GenCmd ;Generate the SCSI command
- beq Error4 ;Bad return, exit
-
- lea SCSICmd(a5),a3 ;Build our SCSI command
- movea.l a3,a0
- move.b #READ_CAP,(a0)+ ;Bit 0-4 = OpCode
- move.b Unit(a5),(a0)+ ;Bit 5-7 = Logical unit number
- clr.b (a0)+ ;Logical Block Addr (MSB)
- clr.b (a0)+ ;Logical Block Addr
- clr.b (a0)+ ;Logical Block Addr
- clr.b (a0)+ ;Logical Block Addr (LSB)
- clr.b (a0)+ ; Not used for this command
- clr.b (a0)+ ; Not used for this command
- clr.b (a0)+ ;Partial Media Indicator
- clr.b (a0) ; Not used for this command
- bsr ScsiOutCmd ;Send the SCSI command
-
- lea DataBuf(a5),a2
- bsr GetData
- bsr SCSIStat
- tst.b d0
- bne.s Error5
-
- lea FmtArgs(a5),a1
- moveq #0,d0
- move.b Device(a5),d0
- move.w d0,(a1)
- move.b Unit(a5),d0
- lsr.b #5,d0
- move.w d0,2(a1)
- lea DataBuf(a5),a0
- move.l (a0),d0 ;Block addr
- move.l d0,4(a1)
- moveq #9,d1
- lsl.l d1,d0
- move.l d0,8(a1)
- lea Capacity.fmt(pc),a0
- bsr Printf ;"Capacity of Device %d, LUN %d = %ld Sectors, %ld Bytes"
- bra.s Cleanup
-
- Error5 addq.w #4,Error(a5) ;"Error reading capacity!!!"
- Error4 addq.w #4,Error(a5) ;"Drive not responding"
- Error3 addq.w #4,Error(a5) ;"NO CLtd Controller Found"
- Error2 addq.w #4,Error(a5) ;"Couldn't open expansion.library"
- Error1 addq.w #4,Error(a5) ;"Unit number must be 0>=15"
- Instruct bsr ReportError ;"Usage: 1> Cap <unit>"
- Cleanup movea.l SysBase,a6
- move.l ExpBase(a5),d0
- beq.s 1$
- movea.l d0,a1
- SYS CloseLibrary
-
- 1$ move.l DosBase(a5),d0
- beq.s Exit
- movea.l d0,a1
- SYS CloseLibrary
-
- Exit move.l InitialSP(a5),sp
- moveq #0,d0
- rts
-
- ********************************************************************
- * NAME: GenCmd()
- * FUNCTION: Setup SCSI bus for command phase & generate a class 00
- * SCSI command.
- * INPUTS: D1 = SCSI Device number
- * A4 = NCR5380 base address
- * RETURN: D0 = 0 if successful, or error code.
- * SCRATCH: None
- ********************************************************************
-
- GenCmd move.l #$40000,d0
- 1$ btst #BCBS_BSY,ncr_bstat(a4) ;Wait for free bus
- beq.s 2$ ;If this doesn't happen after a
- subq.l #1,d0 ; while, exit (rather than hang).
- bmi.s 4$
- bpl.s 1$
- 2$ move.b #PH_DOUT,ncr_tcmd(a4) ;Setup 'Data Out' bus phase
- moveq #1,d0 ;Wait 1 bus settle delay
- lsl.b d1,d0 ;Shift device ID to a bit number
- bset.b #CLTD_HOST,d0 ;OR with ID of Host Controller
- move.b d0,ncr_data(a4) ;Place ID on the data bus
- nop ;Wait 2 deskew delays
- move.b #ASS_BUS!ASS_SEL,ncr_icmd(a4) ;Assert select
- move.l #$40000,d0
- 3$ btst #BCBS_BSY,ncr_bstat(a4) ;Wait for target to respond
- bne.s 5$ ; by asserting busy.
- subq.l #1,d0
- bpl.s 3$ ;If this doesn't happen after a
- 4$ moveq #0,d0 ; while, exit (rather than hang).
- rts
-
- 5$ nop ;Wait 2 deskew delays
- move.b #ASS_NOT,ncr_icmd(a4) ; and deassert select.
- moveq #1,d0
- rts
-
- *************************************************************************
- * NAME: ScsiOutCmd()
- * FUNCTION: Send a class 00 command out the SCSI bus.
- * INPUTS: A3 = Ptr to SCSICmd structure
- * A4 = NCR5380 base address
- * RETURN: None
- * SCRATCH: None
- *************************************************************************
-
- ScsiOutCmd move.l a3,-(sp)
- tst.b (a3) ;If opcode 00 (Test Unit Ready),
- beq.s 1$ ; go directly to Data Out phase.
- move.b #PH_CMD,ncr_tcmd(a4) ;Else, setup 'Command' phase
- bra.s 2$
- 1$ move.b #PH_DOUT,ncr_tcmd(a4) ;Setup 'Data Out' phase
-
- 2$ move.b #ASS_BUS,ncr_icmd(a4) ;Assert the data bus
- 3$ btst #BCBS_REQ,ncr_bstat(a4) ;Wait for target to
- beq.s 3$ ; assert Request.
- btst #PHAS_MATCH,ncr_stat(a4) ;If we're not still in the
- beq.s 5$ ; right phase, exit.
- move.b (a3)+,ncr_data(a4) ;OK, send a byte of command
- move.b #ASS_BUS!ASS_ACK,ncr_icmd(a4) ;Send an ACK to target
- 4$ btst #BCBS_REQ,ncr_bstat(a4) ;Wait for target to
- bne.s 4$ ; deassert Request.
- move.b #ASS_BUS,ncr_icmd(a4) ;Reassert the data bus
- bra.s 3$ ; and send the next byte.
-
- 5$ move.b #ASS_NOT,ncr_icmd(a4) ;We got here because of a glitch
- movea.l (sp)+,a3 ; or we sent all the cmd bytes.
- rts
-
- *************************************************************************
- * NAME: GetData()
- * FUNCTION: Do pseudo-DMA data transfer from SCSI bus.
- * INPUTS: A2 = Data buffer.
- * A4 = NCR5380 base address.
- * RETURN: None
- * SCRATCH: D0-D1/A0-A1
- *************************************************************************
-
- GetData move.l a2,-(sp)
- SYS Disable
- move.b #PH_DIN,ncr_tcmd(a4) ;Data In phase
- 1$ btst #BCBS_REQ,ncr_bstat(a4)
- beq.s 1$
- btst #PHAS_MATCH,ncr_stat(a4)
- beq.s 11$
-
- move.b #MONITOR_BSY,ncr_mode(a4)
- move.b #0,ncr_reset(a4) ;Start DMA receive
- move.b #DMA_REQ,d1
- lea ncr_input(a4),a0
- lea ncr_stat(a4),a1
- 2$ btst d1,(a1)
- beq.s 3$
- move.b (a0),(a2)+
- 3$ btst d1,(a1)
- beq.s 4$
- move.b (a0),(a2)+
- 4$ btst d1,(a1)
- beq.s 5$
- move.b (a0),(a2)+
- 5$ btst d1,(a1)
- beq.s 6$
- move.b (a0),(a2)+
- 6$ btst d1,(a1)
- beq.s 7$
- move.b (a0),(a2)+
- 7$ btst d1,(a1)
- beq.s 8$
- move.b (a0),(a2)+
- 8$ btst d1,(a1)
- beq.s 9$
- move.b (a0),(a2)+
- 9$ btst d1,(a1)
- beq.s 10$
- move.b (a0),(a2)+
- 10$ btst #INT_REQ,(a1)
- beq.s 2$
- move.b #ARBITRATE,ncr_mode(a4)
- tst.b ncr_reset(a4) ;Dummy read
- 11$ SYS Enable
- movea.l (sp)+,a2
- rts
-
- *************************************************************************
- * NAME: SCSIStat()
- * FUNCTION: Test the status of the SCSI bus.
- * INPUTS: A4 = NCR5380 base address
- * RETURN: D0 = Status
- * SCRATCH: None
- *************************************************************************
-
- SCSIStat move.b #PH_STAT,ncr_tcmd(a4) ;Assert I/O and C/D
- 1$ btst #BCBS_REQ,ncr_bstat(a4) ;Wait for target to
- beq.s 1$ ; assert Request.
- moveq #0,d0
- move.b ncr_data(a4),d0 ;Get status byte
- move.b #ASS_ACK,ncr_icmd(a4) ;Send an ACK to target
- 2$ btst #BCBS_REQ,ncr_bstat(a4) ;Wait for target to
- bne.s 2$ ; deassert Request.
- move.b #ASS_NOT,ncr_icmd(a4) ;Drop bus
- move.b #PH_MIN,ncr_tcmd(a4) ;Setup 'Message In' phase
- 3$ btst #BCBS_REQ,ncr_bstat(a4) ;Wait for target to
- beq.s 3$ ; assert Request.
- tst.b ncr_data(a4) ;Dummy read (expected)
- move.b #ASS_ACK,ncr_icmd(a4) ;Send an ACK to target
- 4$ btst #BCBS_REQ,ncr_bstat(a4) ;Wait for target to
- bne.s 4$ ; deassert Request.
- move.b #ASS_NOT,ncr_icmd(a4) ;Drop bus
- rts
-
- *********************************************************************
- * NAME: Printf()
- * FUNCTION: Print formatted strings to stdout.
- * INPUTS: A0 = Format string.
- * A1 = Ptr to arguments.
- * RETURN: None
- * SCRATCH: D0-D1/A0-A1
- *********************************************************************
-
- Printf movem.l a2-a3/a6,-(sp)
- lea KPutChar(pc),a2 ;Byte fill routine
- lea OutBuf(a5),a3
- move.l a3,-(sp)
- movea.l SysBase,a6
- SYS RawDoFmt ;Do it!
- movea.l (sp)+,a0
- bsr.s Puts
- movem.l (sp)+,a2-a3/a6
- rts
-
- KPutChar move.b d0,(a3)+
- rts
-
- *************************************************************************
- * NAME: Puts()
- * FUNCTION: Writes a message to stdout.
- * INPUTS: A0 = Ptr to message.
- * RETURN: None
- * SCRATCH: D0-D1/A0-A1
- *************************************************************************
-
- Puts movem.l d2-d4/a6,-(sp)
- move.l stdout(a5),d4
- bsr.s WriteMsg
- movem.l (sp)+,d2-d4/a6
- rts
-
- *************************************************************************
- * NAME: WriteMsg()
- * FUNCTION: Common subroutine used by FPrintf, Printf, and Puts.
- * INPUTS: A0 = Ptr to message.
- * D4 = FileHandle.
- * RETURN: None
- * SCRATCH: D0-D1/A0-A1
- *************************************************************************
-
- WriteMsg move.l a0,d3
- 1$ tst.b (a0)+
- bne.s 1$
- exg a0,d3
- sub.l a0,d3
- subq.l #1,d3 ;Length
- move.l a0,d2 ;Buffer
- move.l d4,d1 ;FileHandle
- movea.l DosBase(a5),a6
- SYS Write
- rts
-
- *************************************************************************
- * NAME: ReportError()
- * FUNCTION: Sends the appropriate error message to stdout.
- * INPUTS: Error = Offset from ErrStr.tbl.
- * RETURN: None
- * SCRATCH: D0-D1/A0-A1
- *************************************************************************
-
- ReportError move.w Error(a5),d0
- movea.l ErrStr.tbl(pc,d0.w),a0
- bra.s Puts
-
- ErrStr.tbl dl Usage.msg
- dl Error1.msg
- dl Error2.msg
- dl Error3.msg
- dl Error4.msg
- dl Error5.msg
-
- Usage.msg db 'Usage: 1> Cap <unit>',10
- db 'Where <unit> is a number from 0 to 15.',10
- db 'Unit 0 corresponds to Device 1, logical unit 0.',10
- db 'Unit 8 corresponds to Device 1, logical unit 1.',10
- db 'Unit 1 corresponds to Device 2, logical unit 0.',10
- db 'Unit 9 corresponds to Device 2, logical unit 1.',10
- db '(To address the 2nd logical device on an Adaptec',10
- db ' 4000 series, add 8 to the SCSI Device number.)',10,0
- Error1.msg db 'Unit number must be >= 0 and <= 15.',10,0
- Error2.msg db 'Couldn''t open expansion.library.',10,0
- Error3.msg db '** NO CLtd Controller Found **',10,0
- Error4.msg db 'Drive not responding. Wrong unit number?',10,0
- Error5.msg db 'Error reading capacity!!!',0
-
- BannerStr db 'Hard Drive Read Capacity V1.0 - ©1990 by Jeff Lavin',10,10,0
- Capacity.fmt db 'Capacity of Device %d, LUN %d = %ld Sectors, %ld Bytes',10,10,0
-
- DosName db 'dos.library',0
- ExpName db 'expansion.library',0
- cnop 0,4
-
- DT dx.b Work_Sizeof
-
- end
-